﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SmartMathLibrary.Blas
{
    /// <summary>
    /// Specifies the methods that must be implemented by a class to support level 1 BLAS routines. 
    /// </summary>
    [Serializable]
    public abstract class AbstractBlasLevel1 : IBlasLevel1
    {
        /// <summary>
        /// Returns the sum of the absolute values of the elements of a vector. 
        /// </summary>
        /// <param name="n">The number of elements in the vectors x and y.</param>
        /// <param name="x">A reference to a one-dimensional array containing the elements of the vector x.</param>
        /// <param name="incx">The increment for the array x.</param>
        /// <returns>The sum of the absolute values of the elements of a vector.</returns>
        public abstract double Dasum(int n, double[] x, int incx);

        /// <summary>
        /// Evaluates a vector plus the product of a scalar and a vector.
        /// </summary>
        /// <param name="n">The number of elements in the vectors x and y.</param>
        /// <param name="alpha">The scalar value used to multiply the elements of x.</param>
        /// <param name="x">A reference to a one-dimensional array containing the elements of the vector x.</param>
        /// <param name="incx">The increment for the array x.</param>
        /// <param name="y">A reference to a one-dimensional array containing the elements of the vector y. 
        /// The elements of y are overwritten with the result.</param>
        /// <param name="incy">The increment for the array y.</param>
        public abstract void Daxpy(int n, double alpha, double[] x, int incx, double[] y, int incy);

        /// <summary>
        /// Copies a vector.
        /// </summary>
        /// <param name="n">The number of elements in the vectors x and y.</param>
        /// <param name="x">A reference to a one-dimensional array containing the elements of the vector x.</param>
        /// <param name="incx">The increment for the array x.</param>
        /// <param name="y">A reference to a one-dimensional array containing the elements of the vector y. 
        /// The elements of y are overwritten with the elements of x.</param>
        /// <param name="incy">The increment for the array y.</param>
        public abstract void Dcopy(int n, double[] x, int incx, double[] y, int incy);

        /// <summary>
        /// Computes the inner product of two vectors. 
        /// </summary>
        /// <param name="n">The number of elements in the vectors x and y.</param>
        /// <param name="x">A reference to a one-dimensional array containing the elements of the vector x.</param>
        /// <param name="incx">The increment for the array x.</param>
        /// <param name="y">A reference to a one-dimensional array containing the elements of the vector y. 
        /// The elements of y are overwritten with the result.</param>
        /// <param name="incy">The increment for the array y.</param>
        /// <returns>The dot product of the two vectors.</returns>
        public abstract double Ddot(int n, double[] x, int incx, double[] y, int incy);

        /// <summary>
        /// Computes the square root of sum of the squares of the elements of a vector. 
        /// </summary>
        /// <param name="n">The number of elements in the vector x.</param>
        /// <param name="x">A reference to a one-dimensional array containing the elements of the vector x.</param>
        /// <param name="incx">The increment for the array x.</param>
        /// <returns>The square root of sum of the squares of the elements of a vector.</returns>
        public abstract double Dnrm2(int n, double[] x, int incx);

        /// <summary>
        /// Applies a Givens plane rotation.
        /// </summary>
        /// <param name="n">The number of elements in the vectors x and y.</param>
        /// <param name="x">A reference to a one-dimensional array containing the elements of the vector x.</param>
        /// <param name="incx">The increment for the array x.</param>
        /// <param name="y">A reference to a one-dimensional array containing the elements of the vector y.</param>
        /// <param name="incy">The increment for the array y.</param>
        /// <param name="c">The first rotation element, the cosine of the rotation angle.</param>
        /// <param name="s">The second rotation element, the sine of the rotation angle.</param>
        public abstract void Drot(int n, double[] x, int incx, double[] y, int incy, double c, double s);

        /// <summary>
        /// Generates the elements for a Givens plane rotation. 
        /// </summary>
        /// <param name="a">The first element of the input vector. On exit, this value is overwritten with 
        /// the rotated element r.</param>
        /// <param name="b">The second element of the input vector. On exit, this value is overwritten with 
        /// the reconstruction value z.</param>
        /// <param name="c">On exit, this value is overwritten with the first rotation element, the cosine of 
        /// the rotation angle.</param>
        /// <param name="s">On exit, this value is overwritten with the second rotation element, the sine of 
        /// the rotation angle.</param>
        public abstract void Drotg(ref double a, ref double b, ref double c, ref double s);

        /// <summary>
        /// Applies a modified Givens rotation. 
        /// </summary>
        /// <param name="n">The number of elements in the vectors x and y.</param>
        /// <param name="x">A reference to a one-dimensional array containing the elements of the vector x.</param>
        /// <param name="incx">The increment for the array x.</param>
        /// <param name="y">A reference to a one-dimensional array containing the elements of the vector y.</param>
        /// <param name="incy">The increment for the array y.</param>
        /// <param name="param">An array defining the type of transform matrix H used.</param>
        public abstract void Drotm(int n, double[] x, int incx, double[] y, int incy, double[] param);

        /// <summary>
        /// Applies a modified Givens rotation. 
        /// </summary>
        /// <param name="d1">The first scale factor for the modified Givens transform.</param>
        /// <param name="d2">The second scale factor for the modified Givens transform.</param>
        /// <param name="x1">The first element of the input vector. On exit, this value is overwritten with 
        /// the rotated element.</param>
        /// <param name="y1">The second element of the input vector.</param>
        /// <param name="param">An array defining the type of transform matrix H used.</param>
        public abstract void Drotmg(ref double d1, ref double d2, ref double x1, double y1, double[] param);

        /// <summary>
        /// Evaluates the product of a scalar and a vector. 
        /// </summary>
        /// <param name="n">The number of elements in the vector x.</param>
        /// <param name="alpha">The scalar value used to multiply the elements of x.</param>
        /// <param name="x">A reference to a one-dimensional array containing the elements of the vector x. The elements of x are overwritten with the result.</param>
        /// <param name="incx">The increment for the array x.</param>
        public abstract void Dscal(int n, double alpha, double[] x, int incx);

        /// <summary>
        /// Exchanges the elements of two vectors. 
        /// </summary>
        /// <param name="n">The number of elements in the vectors x and y.</param>
        /// <param name="x">A reference to a one-dimensional array containing the elements of the vector x.</param>
        /// <param name="incx">The increment for the array x.</param>
        /// <param name="y">A reference to a one-dimensional array containing the elements of the vector y.</param>
        /// <param name="incy">The increment for the array y.</param>
        public abstract void Dswap(int n, double[] x, int incx, double[] y, int incy);

        /// <summary>
        /// Finds out the index of the element of a vector with maximum absolute value. 
        /// </summary>
        /// <param name="n">The number of elements in the vector x.</param>
        /// <param name="x">A reference to a one-dimensional array containing the elements of the vector x.</param>
        /// <param name="incx">The incx.</param>
        /// <returns>The index of the element of a vector with maximum absolute value. </returns>
        public abstract int Idamax(int n, double[] x, int incx);
    }
}